local skynet = require "skynet"
local socket = require "skynet.socket"
local httpd = require "http.httpd"
local sockethelper = require "http.sockethelper"
local urllib = require "http.url"
local log = require "sky_log"
local uu = require "sky_utils"

local web_agent = {}

local table = table
local string = string

local protocol = "http"

local function response(fd, write, ...)
	--local ok, err = httpd.write_response(write, ...)
    local ok, err = httpd.write_response(write, ...)
	if not ok then
		-- if err == sockethelper.socket_error , that means socket closed.
        log.error("response fd=", fd.."  err="..err)
    end
end

local SSLCTX_SERVER = nil
local function gen_interface(protocol, fd)
	if protocol == "http" then
		return {
			init = nil,
			close = nil,
			read = sockethelper.readfunc(fd),
			write = sockethelper.writefunc(fd),
		}
	elseif protocol == "https" then
		local tls = require "http.tlshelper"
		if not SSLCTX_SERVER then
			SSLCTX_SERVER = tls.newctx()
			-- gen cert and key
			-- openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-cert.pem
			local certfile = skynet.getenv("certfile") or "./server-cert.pem"
			local keyfile = skynet.getenv("keyfile") or "./server-key.pem"
			print(certfile, keyfile)
			SSLCTX_SERVER:set_cert(certfile, keyfile)
		end
		local tls_ctx = tls.newtls("server", SSLCTX_SERVER)
		return {
			init = tls.init_responsefunc(fd, tls_ctx),
			close = tls.closefunc(tls_ctx),
			read = tls.readfunc(fd, tls_ctx),
			write = tls.writefunc(fd, tls_ctx),
		}
	else
		error(string.format("Invalid protocol: %s", protocol))
	end
end

local function send_example_text(method, header, url, body)
    local tmp = {}
    if method then
        table.insert(tmp, string.format("method: %s", method))
    end
    if header.host then
        table.insert(tmp, string.format("host: %s", header.host))
    end
    local path, query = urllib.parse(url)
    table.insert(tmp, string.format("path: %s", path))
    if query then
         local q = urllib.parse_query(query)
        for k, v in pairs(q) do
            table.insert(tmp, string.format("query: %s= %s", k,v))
        end
    end
    table.insert(tmp, "-----header----")
    for k,v in pairs(header) do
        table.insert(tmp, string.format("%s = %s",k,v))
    end
    table.insert(tmp, "-----body----\n" .. body)

    return  table.concat(tmp,"\n")
end

--============================= CMD =============================--
function web_agent.send_msg(url)
    local msg 

    local path, query = urllib.parse(url)
    local cmd
    local param_t = {}
    local q = urllib.parse_query(query)
    for k, v in pairs(q) do
        log.debug("k=", k)
        log.debug("v=", v)
        if k=='cmd' then
            cmd = v
        else
            param_t[k] = v
        end
    end

    if cmd and handle_web and handle_web[cmd] then
        msg = handle_web[cmd](param_t)
        if type(msg) == 'table' then 
            msg = uu.table2string(msg)
        end
    end

    log.debug("param_t=", param_t)

    return msg
end

function web_agent.robot_web_info(url)
    local param_t = {}
    local path, query = urllib.parse(url)
    if query then
        --query = "platid=124&tid=&cmd=call&card2=0.5%2C0.5%2C1&card3=0.5%2C0.5%2C1&card4=0.5%2C0.5%2C1&card5=0.5%2C0.5%2C1&card6=0.75%2C0.75%2C1.25&card7=0.75%2C0.75%2C1.25&card8=0.75%2C0.75%2C1.25&card9=0.75%2C0.75%2C1.25&card10=1.5%2C1.5%2C2&card11=1.5%2C1.5%2C2&card12=2%2C2%2C2.5&card13=2%2C2%2C2.5&card14=2.5%2C2.5%2C3&call_0=0%2C16.1251&call_7=16.125%2C18.8&call_8=18.8%2C21.475&call_9=21.475%2C24.15&call_10=24.15%2C26.825&call_11=26.825%2C29.5&call_12=1000%2C2000&call_13=2000%2C3001"
        local q = urllib.parse_query(query)
        for k, v in pairs(q) do
            --table.insert(param_t, string.format("query: %s = %s", k,v))
            param_t[k] = v
        end

        if next(param_t)~=nil then 
            skynet.send(".robot_manager", "lua", "web_ctrl_msg", param_t)
        end
    end

    --local file = assert(io.open("../../robot/common/robot_gui.html", "r"))
    local html = skynet.getenv("web_index")
    local file
    if html then
        file = assert(io.open(html, "r"))
    else
        file = assert(io.open("../../base/web/robot_gui.html", "r"))
    end
	local data = file:read("*a")
	file:close()

	return data
end

function web_agent.handler(session, source, client_fd, addr)
    socket.start(client_fd)
    local interface = gen_interface(protocol, client_fd)
    --https init
    if interface.init then
        interface.init()
    end
    -- limit request body size to 8192 (you can pass nil to unlimit)
    local code, url, method, header, body = httpd.read_request(interface.read, 8192)
    --log.debug("code=", code)
    --log.debug("url=", url)
    --log.debug("method=", method)
    --log.debug("header=", header)
    --log.debug("body=", body)
    if code then
        if code ~= 200 then
            response(client_fd, interface.write, code)
        else
            --local msg = send_example_text(method, header, url, body)
            local msg = ''
            local node_name = skynet.getenv("node_name")
            local nn = require "sky_node"
            if tonumber(nn[node_name])>=60000 then 
                msg = web_agent.robot_web_info(url)
            end

            response(client_fd, interface.write, code, msg)
        end
    else
        if url == sockethelper.socket_error then
            log.info("socket closed")
        else
            log.info(url)
        end
    end
    socket.close(client_fd)
    if interface.close then
        interface.close()
    end

    skynet.exit()
end

skynet.start(function ()
    skynet.dispatch("lua", function (session, source, client_fd, addr)
        web_agent.handler(session, source, client_fd, addr)
    end)
end)